package com.gitee.wsl.doc.prosemirror.ui.command

import com.gitee.wsl.doc.prosemirror.state.CommandDispatch
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.state.selection.TextSelection
import com.gitee.wsl.doc.prosemirror.ui.EditorView
import com.gitee.wsl.ext.base.ifValue


open class CollapseCmd(
    outerView: EditorView,
    val dir:Int,//(1|-1)
    val requireOnBorder: Boolean,
    val requireEmptySelection: Boolean = true
): AbstractEditorViewCommand(outerView) {
    override fun exec(
        state: EditorState,
        dispatch:CommandDispatch?
    ): Boolean {
        // get selection info
        val outerState: EditorState = outerView.state
        val outerTo = outerState.selection.to
        val outerFrom = outerState.selection.from
        val innerTo = state.selection.to
        val innerFrom = state.selection.from

        // only exit math node when selection is empty
        if(requireEmptySelection && innerTo != innerFrom) { return false }
        val currentPos = (dir > 0).ifValue( innerTo , innerFrom)

        // when requireOnBorder is TRUE, collapse only when cursor
        // is about to leave the bounds of the math node
        if(requireOnBorder) {
            // (subtract two from nodeSize to account for start and end tokens)
            val nodeSize = state.doc.nodeSize - 2

            // early return if exit conditions not met
            if(dir > 0 && currentPos < nodeSize) { return false }
            if(dir < 0 && currentPos > 0)        { return false }
        }

        // all exit conditions met, so close the math node by moving the cursor outside
        if(dispatch!=null) {
            // set outer selection to be outside of the nodeview
            val targetPos = (dir > 0).ifValue( outerTo , outerFrom)

            outerView.dispatch(
                outerState.tr.setSelection(
                    TextSelection.create(outerState.doc, targetPos)
                )
            )

            // must return focus to the outer view, otherwise no cursor will appear
            outerView.focus()
        }

        return true
    }

}




